/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc. 
 *  
 * SPDX-License-Identifier: Apache-2.0.
 * 
 * @Date: 2021-07-19 11:13:54
 * @LastEditTime: 2021-07-23 09:37:25
 * @Description:  This files is for 
 * 
 * @Modify History: 
 *  Ver   Who        Date         Changes
 * ----- ------     --------    --------------------------------------
 */

#ifndef BSP_DRIVERS_NOR_QSPI_HW_H
#define BSP_DRIVERS_NOR_QSPI_HW_H

#ifdef __cplusplus
extern "C"
{
#endif

#include "ft_io.h"
#include "kernel.h"
#include "qspi.h"

/* register definition */
#define QSPI_REG_CAP_OFFSET (0x00)       /* Flash capacity setting register */
#define QSPI_REG_RD_CFG_OFFSET (0x04)    /* Address access reads configuration registers */
#define QSPI_REG_WR_CFG_OFFSET (0x08)    /* Write buffer flush register */
#define QSPI_REG_FLUSH_OFFSET (0x0C)     /* Write buffer flush register */
#define QSPI_REG_CMD_PORT_OFFSET (0x10)  /* Command port register */
#define QSPI_REG_ADDR_PORT_OFFSET (0x14) /* Address port register */
#define QSPI_REG_HD_PORT_OFFSET (0x18)   /* Upper bit port register */
#define QSPI_REG_LD_PORT_OFFSET (0x1C)   /* low bit port register */
#define QSPI_REG_FUN_SET_OFFSET (0x20)   /* CS setting register  */
#define QSPI_REG_WIP_RD_OFFSET (0x24)    /* WIP reads the Settings register */
#define QSPI_REG_WP_OFFSET (0x28)        /* WP register */
#define QSPI_REG_MODE_OFFSET (0x2C)      /* Mode setting register */

/* QSPI_CAP */
#define QSPI_CAP_FLASH_NUM(data) ((data) << 3) /* Flash number */
#define QSPI_CAP_FLASH_CAP(data) ((data) << 0) /*  The flash capacity */

#define QSPI_CAP_FLASH_CAP_MASK   GENMASK(2, 0)

/* RD_CFG */
#define QSPI_RD_CFG_CMD(data) ((data) << 24)       /* Read Command */
#define QSPI_RD_CFG_THROUGH(data) ((data) << 23)   /* The programming flag in the status register */
#define QSPI_RD_CFG_TRANSFER(data) ((data) << 20)  /*  */
#define QSPI_RD_CFG_ADDR_SEL(data) ((data) << 19)  /*  */
#define QSPI_RD_CFG_LATENCY(data) ((data) << 18)   /*  */
#define QSPI_RD_CFG_MODE_BYTE(data) ((data) << 17) /*  */
#define QSPI_RD_CFG_CMD_SIGN(data) ((data) << 9)   /*  */
#define QSPI_RD_CFG_DUMMY(data) ((data) << 4)      /*  */
#define QSPI_RD_CFG_D_BUFFER(data) ((data) << 3)   /*  */
#define QSPI_RD_CFG_SCK_SEL(data) ((data) << 0)    /*  */

#define QSPI_RD_CFG_CMD_MASK        GENMASK(31, 24)
#define QSPI_RD_CFG_SCK_SEL_MASK    GENMASK(2, 0)
#define QSPI_RD_CFG_TRANSFER_MASK   GENMASK(22, 20)
#define QSPI_RD_CFG_ADDR_SEL_MASK   QSPI_RD_CFG_ADDR_SEL(0x1)
#define QSPI_RD_CFG_DUMMY_MASK      GENMASK(8, 4)

/* QSPI_WR_CFG */
#define QSPI_WR_CFG_CMD(data) ((data) << 24)
#define QSPI_WR_CFG_WAIT(data) ((data) << 9)
#define QSPI_WR_CFG_THROUGH(data) ((data) << 8)
#define QSPI_WR_CFG_TRANSFER(data) ((data) << 5)
#define QSPI_WR_CFG_ADDRSEL(data) ((data) << 4)
#define QSPI_WR_CFG_MODE(data) ((data) << 3)
#define QSPI_WR_CFG_SCK_SEL(data) ((data) << 0)

#define QSPI_WR_CFG_CMD_MASK        GENMASK(31, 24)
#define QSPI_WR_CFG_SCK_SEL_MASK    GENMASK(2, 0)
#define QSPI_WR_CFG_ADDRSEL_MASK    QSPI_WR_CFG_ADDRSEL(0x1)

/* QSPI_CMD_PORT */
#define QSPI_CMD_PORT_CMD(data) ((data) << 24)
#define QSPI_CMD_PORT_WAIT(data) ((data) << 22)
#define QSPI_CMD_PORT_THROUGH(data) ((data) << 21)
#define QSPI_CMD_PORT_CS(data) ((data) << 19)
#define QSPI_CMD_PORT_TRANSFER(data) ((data) << 16)
#define QSPI_CMD_PORT_CMD_ADDR(data) ((data) << 15)
#define QSPI_CMD_PORT_LATENCY(data) ((data) << 14)
#define QSPI_CMD_PORT_DATA_TRANS(data) ((data) << 13)
#define QSPI_CMD_PORT_ADDR_SEL(data) ((data) << 12)
#define QSPI_CMD_PORT_DUMMY(data) ((data) << 7)
#define QSPI_CMD_PORT_P_BUFFER(data) ((data) << 6)
#define QSPI_CMD_PORT_RW_NUM(data) ((data) << 3)
#define QSPI_CMD_PORT_CLK_SEL(data) ((data) << 0)

#define QSPI_CMD_PORT_RW_NUM_MASK   GENMASK(5, 3)
#define QSPI_CMD_PORT_CLK_SEL_MASK  GENMASK(2, 0)
#define QSPI_CMD_PORT_CS_MASK       GENMASK(20, 19)
#define QSPI_CMD_PORT_CMD_MASK      GENMASK(31, 24)
#define QSPI_CMD_PORT_ADDR_SEL_MASK QSPI_CMD_PORT_ADDR_SEL(0x1)

/* QSPI_FUN_SET */
#define QSPI_FUN_SET_CS_HOLD(data) ((data) << 24)
#define QSPI_FUN_SET_CS_SETUP(data) ((data) << 16)
#define QSPI_FUN_SET_CS_DELAY(data) ((data) << 0)

/* QSPI_WIP_RD */
#define QSPI_WIP_RD_CMD(data) ((data) << 24)
#define QSPI_WIP_RD_TRANSFER(data) ((data) << 3)
#define QSPI_WIP_RD_SCK_SEL(data) ((data) << 0)

/* QSPI_WP */
#define QSPI_WP_EN(data) ((data) << 17)
#define QSPI_WP_WP(data) ((data) << 16)
#define QSPI_WP_HOLD(data) ((data) << 8)
#define QSPI_WP_SETUP(data) ((data) << 0)

/* QSPI_MODE */
#define QSPI_MODE_VALID(data) ((data) << 8)
#define QSPI_MODE_MODE(data) ((data) << 0)

typedef enum
{
    QSPI_CMD_READ = 0x01,
    QSPI_CMD_WRITE = 0x02,
}QSpiCmdFlags;

/**
 * @name: QSPI_READ_REG32
 * @msg:  读取QSPI寄存器
 * @param {u32} addr 定时器的基地址
 * @param {u32} reg_offset   定时器的寄存器的偏移
 * @return {u32} 寄存器参数
 */
#define QSPI_READ_REG32(addr, reg_offset) FtIn32(addr + (u32)reg_offset)

/**
 * @name: QSPI_WRITE_REG32
 * @msg:  写入QSPI寄存器
 * @param {u32} addr 定时器的基地址
 * @param {u32} reg_offset   定时器的寄存器的偏移
 * @param {u32} reg_value    写入寄存器参数
 * @return {void}
 */
#define QSPI_WRITE_REG32(addr, reg_offset, reg_value) FtOut32(addr + (u32)reg_offset, (u32)reg_value)


/* QSPI Register Operations */
#define QSPI_BASE_ADDR(pCtrl) ((pCtrl)->config.baseAddr)
#define QSPI_CAP_WRITE(pCtrl, regVal) QSPI_WRITE_REG32(QSPI_BASE_ADDR(pCtrl), QSPI_REG_CAP_OFFSET, regVal)
#define QSPI_CAP_READ(pCtrl) QSPI_READ_REG32(QSPI_BASE_ADDR(pCtrl), QSPI_REG_CAP_OFFSET)
#define QSPI_CMD_WRITE(pCtrl, regVal) QSPI_WRITE_REG32(QSPI_BASE_ADDR(pCtrl), QSPI_REG_CMD_PORT_OFFSET, regVal) 
#define QSPI_CMD_READ(pCtrl) QSPI_READ_REG32(QSPI_BASE_ADDR(pCtrl), QSPI_REG_CMD_PORT_OFFSET)
#define QSPI_LD_WRITE(pCtrl, regVal) QSPI_WRITE_REG32(QSPI_BASE_ADDR(pCtrl), QSPI_REG_LD_PORT_OFFSET, regVal)  
#define QSPI_LD_READ(pCtrl) QSPI_READ_REG32(QSPI_BASE_ADDR(pCtrl), QSPI_REG_LD_PORT_OFFSET)
#define QSPI_RD_CFG_WRITE(pCtrl, regVal) QSPI_WRITE_REG32(QSPI_BASE_ADDR(pCtrl), QSPI_REG_RD_CFG_OFFSET, regVal)  
#define QSPI_RD_CFG_READ(pCtrl) QSPI_READ_REG32(QSPI_BASE_ADDR(pCtrl), QSPI_REG_RD_CFG_OFFSET)
#define QSPI_WR_CFG_WRITE(pCtrl, regVal) QSPI_WRITE_REG32(QSPI_BASE_ADDR(pCtrl), QSPI_REG_WR_CFG_OFFSET, regVal)
#define QSPI_WR_CFG_READ(pCtrl) QSPI_READ_REG32(QSPI_BASE_ADDR(pCtrl), QSPI_REG_WR_CFG_OFFSET)
#define QSPI_DAT_WRITE(addr, dat) FtOut32((addr), (u32)(dat))
#define QSPI_FLUSH(pCtrl) QSPI_WRITE_REG32(QSPI_BASE_ADDR(pCtrl), QSPI_REG_FLUSH_OFFSET, 0x1)
#define QSPI_CMD_ADDR_WRITE(pCtrl, regVal) QSPI_WRITE_REG32(QSPI_BASE_ADDR(pCtrl), QSPI_REG_ADDR_PORT_OFFSET, regVal)
#define QSPI_CMD_ADDR_READ(pCtrl) QSPI_READ_REG32(QSPI_BASE_ADDR(pCtrl), QSPI_REG_ADDR_PORT_OFFSET)

/* Lowlayer API */
u32 QSpiGetLdPortData(QSpiCtrl *pCtrl, u8 *pBuf, size_t len);
u32 QSpiSetLdPortData(QSpiCtrl *pCtrl, const u8 *pBuf, size_t len);
u32 QSpiWaitForCmd(QSpiCtrl *pCtrl);
void QSpiEnableWrite(QSpiCtrl *pCtrl);
void QSpiDisableWrite(QSpiCtrl *pCtrl);
void QSpiReset(QSpiCtrl *pCtrl);

#ifdef __cplusplus
}
#endif

#endif